package com.zhxy.filter;

import com.zhxy.bean.User;
import com.zhxy.constants.Constants;
import com.zhxy.result.CodeEnum;
import com.zhxy.result.R;
import com.zhxy.service.RedisService;
import com.zhxy.utils.JSONUtils;
import com.zhxy.utils.JWTUtils;
import com.zhxy.utils.ResponseUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.experimental.Accessors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * Token验证过滤器
 */
@Component
public class TokenVerifyFilter extends OncePerRequestFilter {

    @Autowired
    private RedisService redisService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        // 如果是登录请求，此时还没有JWT，则不需要JWT认证
        if (request.getRequestURI().equals(Constants.LOGIN_URI)){
            filterChain.doFilter(request,response);
        }else {

            // 从请求头中获取Token
            String token = request.getHeader("Authorization");
            if (!StringUtils.hasText(token)){
                // 登录失败的统一返回结果
                R result = R.FALL(CodeEnum.TOKEN_IS_NULL);
                // 将结果转换为json对象
                String json = JSONUtils.toJSON(result);
                // 将结果响应给前端
                ResponseUtils.write(response,json);
                return;
            }

            // Token被修改
            if (!JWTUtils.verifyJWT(token)){
                R result = R.FALL(CodeEnum.TOKEN_IS_ERROR);
                String json = JSONUtils.toJSON(result);
                ResponseUtils.write(response,json);
                return;
            }

            // 对Token进行解析
            User user = JWTUtils.parseUserFromJWT(token);
            // 从Redis中获取Token
            String redisToken= (String) redisService.getValue(Constants.REDIS_JWT_KEY+user.getId());

            // 从Redis中获取Token
            if (!StringUtils.hasText(redisToken)){
                R result = R.FALL(CodeEnum.TOKEN_IS_EXPIRED);
                String json = JSONUtils.toJSON(result);
                ResponseUtils.write(response,json);
                return;
            }

            // 生成的Token与redis的Token不一致
            if (!token.equals(redisToken)){
                R result = R.FALL(CodeEnum.TOKEN_BE_UPDATE);
                String json = JSONUtils.toJSON(result);
                ResponseUtils.write(response,json);
            }

            // Token验证成功
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user,user.getLoginPwd(),user.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);

            // 使用SpringBoot的线程池来刷新Token
            new Thread(()->{
                String rememberMe = request.getHeader("rememberMe");
                if (Boolean.parseBoolean(rememberMe)){
                    redisService.expire(Constants.REDIS_JWT_KEY+user.getId(),Constants.TIMEOUT, TimeUnit.SECONDS);
                }else {
                    redisService.expire(Constants.REDIS_JWT_KEY+user.getId(),Constants.DEFAULT_TIMEOUT,TimeUnit.SECONDS);
                }
            });

            // 验证通过，继续执行其他Filter
            filterChain.doFilter(request,response);
        }
    }
}
